home *** CD-ROM | disk | FTP | other *** search
- (*===========================================================================*)
- (* Memory handler *)
- (* *)
- (* Copyright 1989, 1990, 1991 by H. Roy Engehausen. All rights reserved. *)
- (* *)
- (*===========================================================================*)
-
- {$O+}
-
- {$DEFINE POINT_CHK}
- {$DEFINE FREE_CHK}
- {$UNDEF DEBUG}
- {$UNDEF DEBUG2} (* Trace allocate/free *)
- {$UNDEF DEBUG3} (* Partial free *)
-
- UNIT BBMEM;
-
- INTERFACE
-
- USES
- bbdummy;
-
- TYPE
-
- mem_list_start = BYTE;
-
- mem_list_ptr = ^mem_list;
-
- mem_list = RECORD
- next_mem_list : mem_list_ptr;
- mem_name : mem_id_str;
- mem_size : WORD;
- mem_start : mem_list_start;
- END;
-
- CONST
- mem_overhead = SIZEOF(mem_list) - SIZEOF(mem_list_start);
-
- memid_call_scanned = 'CS';
- search_memory_block_id = 'MSB';
-
-
- FUNCTION get_task_mem(name_of_mem : mem_id_str;
- mem_size_to_get : WORD) : POINTER;
-
- FUNCTION get_task_text_buff(name_of_mem : mem_id_str) : POINTER;
-
- FUNCTION find_task_mem_addr(name_of_mem : mem_id_str) : POINTER;
-
- FUNCTION find_task_mem_size(name_of_mem : mem_id_str) : WORD;
-
- PROCEDURE free_task_mem(name_of_mem : mem_id_str; free_all : BOOLEAN);
-
- PROCEDURE free_task_mem_end(name_of_mem : mem_id_str; size_to_free : WORD);
-
- PROCEDURE move_task_mem(mem_id : mem_id_str;
- from_tcb : tcb_ptr;
- to_tcb : tcb_ptr);
-
- PROCEDURE free_task_mem_all(this_tcb : tcb_ptr);
-
- IMPLEMENTATION
-
- USES
- bbbug,
- bbmisc3,
- bbtrace;
-
- (*===========================================================================*)
- (* Get task memory *)
- (*===========================================================================*)
-
- FUNCTION get_task_mem(name_of_mem : mem_id_str;
- mem_size_to_get : WORD) : POINTER;
-
- VAR
- new_mem : mem_list_ptr;
- size : LONGINT;
-
- BEGIN;
-
- {$IFDEF POINT_CHK}
- IF active_tcb^.stor_list <> NIL THEN
- test_pointer(active_tcb^.stor_list);
- {$ENDIF}
-
- size := LONGINT(mem_overhead) + mem_size_to_get;
-
- GETMEM(new_mem, size);
-
- {$IFDEF DEBUG2}
- trace_data('MEG', size, new_mem, name_of_mem);
- {$ENDIF}
-
- new_mem^.next_mem_list := active_tcb^.stor_list;
- new_mem^.mem_name := name_of_mem;
- new_mem^.mem_size := mem_size_to_get;
-
- active_tcb^.stor_list := new_mem;
-
- get_task_mem := ADDR(new_mem^.mem_start);
-
- {$IFDEF DEBUG}
- WRITELN('MEM get - ', name_of_mem, ' - ', mem_size_to_get,
- ' - ', p2x(active_tcb^.stor_list),
- ' - ', p2x(ADDR(new_mem^.mem_start)));
- {$ENDIF}
-
- END;
-
- (*===========================================================================*)
- (* Get a text buffer *)
- (*===========================================================================*)
-
- FUNCTION get_task_text_buff(name_of_mem : mem_id_str) : POINTER;
-
- VAR
- size_to_get : LONGINT;
-
- BEGIN;
-
- size_to_get := MAXAVAIL div 2;
-
- IF size_to_get > 10240 THEN
- size_to_get := 10240;
-
- get_task_text_buff := get_task_mem(name_of_mem, size_to_get);
-
- END;
-
- (*===========================================================================*)
- (* Find task memory *)
- (*===========================================================================*)
-
- FUNCTION find_task_mem(name_of_mem : mem_id_str) : mem_list_ptr;
-
- VAR
- look_mem : mem_list_ptr;
-
- BEGIN;
-
- look_mem := active_tcb^.stor_list;
-
- WHILE (look_mem <> NIL) AND (look_mem^.mem_name <> name_of_mem) DO
- look_mem := look_mem^.next_mem_list;
-
- find_task_mem := look_mem;
-
- END;
-
- (*===========================================================================*)
- (* Find the address of a task memory block *)
- (*===========================================================================*)
-
- FUNCTION find_task_mem_addr(name_of_mem : mem_id_str) : POINTER;
-
- VAR
- look_mem : mem_list_ptr;
-
- BEGIN;
-
- look_mem := find_task_mem(name_of_mem);
-
- IF look_mem <> NIL THEN
- find_task_mem_addr := ADDR(look_mem^.mem_start)
- ELSE
- find_task_mem_addr := NIL;
-
- END;
-
- (*===========================================================================*)
- (* Find the size of a task memory block *)
- (*===========================================================================*)
-
- FUNCTION find_task_mem_size(name_of_mem : mem_id_str) : WORD;
-
- VAR
- look_mem : mem_list_ptr;
-
- BEGIN;
-
- look_mem := find_task_mem(name_of_mem);
-
- IF look_mem <> NIL THEN
- find_task_mem_size := look_mem^.mem_size
- ELSE
- find_task_mem_size := 0;
-
- END;
-
- (*===========================================================================*)
- (* Free task memory block -- May free all with the same name *)
- (*===========================================================================*)
-
- PROCEDURE free_task_mem(name_of_mem : mem_id_str; free_all : BOOLEAN);
-
- VAR
- last_mem : mem_list_ptr;
- look_mem : mem_list_ptr;
- next_mem : mem_list_ptr;
- size : LONGINT;
-
- BEGIN;
-
- {$IFDEF DEBUG}
- WRITELN('MEM free - ', name_of_mem);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Initialize the loop *)
- (*-----------------------------------------------------------------------*)
-
- last_mem := NIL;
- look_mem := active_tcb^.stor_list;
-
- (*-----------------------------------------------------------------------*)
- (* Look thru the memory list *)
- (*-----------------------------------------------------------------------*)
-
- WHILE look_mem <> NIL DO
- BEGIN;
-
- {$IFDEF POINT_CHK}
- test_pointer(look_mem);
- {$ENDIF}
-
- {$IFDEF DEBUG}
- WRITELN('MEM free loop - ', p2x(look_mem), ' - ',
- look_mem^.mem_name);
- {$ENDIF}
-
- (*-------------------------------------------------------------------*)
- (* Where do we go from here? *)
- (*-------------------------------------------------------------------*)
-
- next_mem := look_mem^.next_mem_list;
-
- (*-------------------------------------------------------------------*)
- (* Check for a match. If none, establish a new back pointer *)
- (*-------------------------------------------------------------------*)
-
- IF look_mem^.mem_name <> name_of_mem THEN
- last_mem := look_mem
- ELSE
- BEGIN;
-
- (*---------------------------------------------------------------*)
- (* Remove this block from the thread's chain *)
- (*---------------------------------------------------------------*)
-
- IF last_mem = NIL THEN
- active_tcb^.stor_list := look_mem^.next_mem_list
- ELSE
- last_mem^.next_mem_list := look_mem^.next_mem_list;
-
- (*---------------------------------------------------------------*)
- (* Free the space *)
- (*---------------------------------------------------------------*)
-
- size := LONGINT(mem_overhead) + look_mem^.mem_size;
-
- {$IFDEF DEBUG}
- WRITELN('MEM free now - ', p2x(look_mem), ' - ', size);
- heap_dump;
- {$ENDIF}
-
- {$IFDEF DEBUG2}
- trace_data('MEF', size, look_mem, look_mem^.mem_name);
- {$ENDIF}
-
- FILLCHAR(look_mem^, size, $F1);
- FREEMEM(look_mem, size);
-
- {$IFDEF FREE_CHK}
- test_free_list;
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* If we only want to free the top one, we are done *)
- (*---------------------------------------------------------------*)
-
- IF NOT free_all THEN EXIT;
-
- END;
-
- (*-------------------------------------------------------------------*)
- (* Chain forward *)
- (*-------------------------------------------------------------------*)
-
- look_mem := next_mem;
-
- END;
-
- END;
-
- (*===========================================================================*)
- (* Free the end of an item *)
- (*===========================================================================*)
-
- PROCEDURE free_task_mem_end(name_of_mem : mem_id_str; size_to_free : WORD);
-
- VAR
- i : WORD;
- l : LONGINT;
- look_mem : mem_list_ptr;
- offset : WORD;
- segment : WORD;
-
-
- BEGIN;
-
- {$IFDEF DEBUG}
- WRITELN('MEM free end - ', name_of_mem, ' / ', size_to_free);
- {$ENDIF}
-
- {$IFDEF DEBUG3}
- WRITELN('MEM free end - ', name_of_mem, ' / ', size_to_free);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* If nothing to free then leave *)
- (*-----------------------------------------------------------------------*)
-
- IF size_to_free = 0 THEN EXIT;
-
- (*-----------------------------------------------------------------------*)
- (* Find the control block to free *)
- (*-----------------------------------------------------------------------*)
-
- look_mem := find_task_mem(name_of_mem);
-
- (*-----------------------------------------------------------------------*)
- (* If nothing found then exit *)
- (*-----------------------------------------------------------------------*)
-
- IF look_mem = NIL THEN EXIT;
-
- {$IFDEF POINT_CHK}
- test_pointer(look_mem);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Get current data size and the full control block size *)
- (*-----------------------------------------------------------------------*)
-
- offset := look_mem^.mem_size;
- l := offset + LONGINT(mem_overhead);
-
- (*-----------------------------------------------------------------------*)
- (* Calculate how much will be left *)
- (*-----------------------------------------------------------------------*)
-
- i := offset - size_to_free;
-
- (*-----------------------------------------------------------------------*)
- (* If nothing then free it all *)
- (*-----------------------------------------------------------------------*)
-
- IF i <= 0 THEN
- BEGIN;
- free_task_mem(name_of_mem, FALSE);
-
- {$IFDEF FREE_CHK}
- test_free_list;
- {$ENDIF}
-
- EXIT;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Put updated size back *)
- (*-----------------------------------------------------------------------*)
-
- look_mem^.mem_size := i;
-
- (*-----------------------------------------------------------------------*)
- (* Change size to true block size *)
- (*-----------------------------------------------------------------------*)
-
- INC(i, mem_overhead);
- INC(offset, mem_overhead);
-
- (*-----------------------------------------------------------------------*)
- (* If new TURBO storage manager then only deal in chunks *)
- (*-----------------------------------------------------------------------*)
-
- {$IFNDEF VER55}
-
- i := 8 * ((i + 7) DIV 8);
-
- {$IFDEF DEBUG3}
- WRITELN('MEM free end chunk - ', offset, ' / ', i);
- {$ENDIF}
-
- IF offset <= i THEN EXIT;
-
- size_to_free := offset - i;
-
- {$IFDEF DEBUG3}
- WRITELN('MEM free end chuck - ', size_to_free, ' / ', i);
- {$ENDIF}
-
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Calculate start of area to free *)
- (*-----------------------------------------------------------------------*)
-
- {$IFDEF DEBUG}
- WRITELN('MEM free end start - ', p2x(look_mem), ' / ', i);
- {$ENDIF}
-
- {$IFDEF DEBUG3}
- WRITELN('MEM free end start - ', p2x(look_mem), ' / ', i);
- {$ENDIF}
-
- i := i + OFS(look_mem^);
-
- {$IFDEF DEBUG}
- WRITELN('MEM free end calc - ', p2x(look_mem), ' / ', i);
- {$ENDIF}
-
- {$IFDEF DEBUG3}
- WRITELN('MEM free end calc - ', p2x(look_mem), ' / ', i);
- {$ENDIF}
-
- segment := SEG(look_mem^);
- segment := segment + i DIV 16;
- i := i AND $F;
- look_mem := PTR(segment, i);
-
- {$IFDEF POINT_CHK}
- test_pointer(look_mem);
- {$ENDIF}
-
- {$IFDEF DEBUG}
- WRITELN('MEM free end actual - ', p2x(look_mem), ' / ', size_to_free);
- {$ENDIF}
-
- {$IFDEF DEBUG2}
- trace_data('MES', size_to_free, look_mem, name_of_mem);
- {$ENDIF}
-
- {$IFDEF DEBUG3}
- WRITELN('MEM free end actual - ', p2x(look_mem), ' / ', size_to_free);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Free it *)
- (*-----------------------------------------------------------------------*)
-
- FILLCHAR(look_mem^, size_to_free, $F2);
- FREEMEM(look_mem, size_to_free);
-
- {$IFDEF FREE_CHK}
- test_free_list;
- {$ENDIF}
-
- END;
-
- (*===========================================================================*)
- (* Move task memory *)
- (*===========================================================================*)
-
- PROCEDURE move_task_mem(mem_id : mem_id_str;
- from_tcb : tcb_ptr;
- to_tcb : tcb_ptr);
- VAR
- last_mem : mem_list_ptr;
- look_mem : mem_list_ptr;
-
- BEGIN;
-
- {$IFDEF DEBUG}
- WRITELN('MEM move - ', mem_id);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Locate the block we want *)
- (*-----------------------------------------------------------------------*)
-
- last_mem := NIL;
- look_mem := from_tcb^.stor_list;
-
- WHILE (look_mem <> NIL) AND (look_mem^.mem_name <> mem_id) DO
- BEGIN;
- last_mem := look_mem;
- look_mem := look_mem^.next_mem_list;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* If nothing found then exit *)
- (*-----------------------------------------------------------------------*)
-
- IF look_mem = NIL THEN
- EXIT;
-
- {$IFDEF POINT_CHK}
- test_pointer(look_mem);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Remove this memory from old thread *)
- (*-----------------------------------------------------------------------*)
-
- IF last_mem = NIL THEN
- from_tcb^.stor_list := look_mem^.next_mem_list
- ELSE
- last_mem^.next_mem_list := look_mem^.next_mem_list;
-
- (*-----------------------------------------------------------------------*)
- (* Add to head of new thread's list *)
- (*-----------------------------------------------------------------------*)
-
- look_mem^.next_mem_list := to_tcb^.stor_list;
-
- to_tcb^.stor_list := look_mem;
-
- END;
-
- (*===========================================================================*)
- (* Free all memory for a task *)
- (*===========================================================================*)
-
- PROCEDURE free_task_mem_all(this_tcb : tcb_ptr);
-
- VAR
- next_mem : mem_list_ptr;
- size : LONGINT;
- this_mem : mem_list_ptr;
-
- BEGIN;
-
- (*-----------------------------------------------------------------------*)
- (* Free random storage *)
- (*-----------------------------------------------------------------------*)
-
- this_mem := this_tcb^.stor_list;
-
- IF this_mem <> NIL THEN
- BEGIN;
-
- this_tcb^.stor_list := NIL;
-
- REPEAT
-
- next_mem := this_mem^.next_mem_list;
- size := LONGINT(mem_overhead) + this_mem^.mem_size;
-
- FREEMEM(this_mem, size);
-
- this_mem := next_mem;
-
- UNTIL this_mem = NIL;
-
- END;
-
- END;
-
- END.